﻿$(document).ready(function() {
designer = new TemplateDesigner("#Toolbox", ".Designer", "#ToolboxTreeContainer");
});

var designer ;

TemplateDesigner = function(toolboxContainer, designer, tree) {
    this.container = toolboxContainer;
    this.enableDropOn($(designer), true);
    this.treeContainer = tree;
    this.tools = [];
    this.elementTree = new ElementTree();
    this.register();
    this.render();
    this.initializeTree();
    this.arrangePageWidth();
}

Element = function(id, type , settings , childs) {
    this.id = id || UID(); 
    this.type = type;
    this.settings = settings;
    this.childs = childs || [];
}
var ElementTree = function() {
    this.items = []
};

ElementTree.prototype = {
    Add: function(item) {
        this.items.push(item);
        
    }

}

Control = function(isZone, key, name, zoneSelector,template ) {
    ///	<summary>
    ///
    ///	</summary>
    ///	<param name="isZone" type="Bool">
    ///		1: Indicates if the toolbox item can contain other toolbox items
    ///	</param>
    this.key = key;
    this.name = name;
    this.template = template;
    this.zone = isZone;
    this.multipleDropZoneSelector = zoneSelector;
}

///Note that inheritance occurs automatically as part of the process of looking up a property value. 
//Properties are not copied from the prototype object into new objects; they merely appear as if they 
//were properties of those objects. This has two important implications. First, the use of prototype 
//objects can dramatically decrease the amount of memory required by each object because the object 
//can inherit many of its properties. The second implication is that an object inherits properties 
//even if they are added to its prototype after the object is created. This means that it is possible 
//(though not necessarily a good idea) to add new methods to existing classes.
TemplateDesigner.prototype = {

    arrangePageWidth: function() {
        $(".page").css({ width: '94%' });
    },
    ///	<summary>
    ///		1: Initialize the toolbox possibilities into the toolbox array
    ///	</summary>
    register: function() {
        this.tools.push(new Control(true, "zone", "Zone", "", "<div id='{0}' class='tool zone Designer Small' > Test Content <br/><br/> </div>"));
        this.tools.push(new Control(false, "div", "Div", "", "<div id='{0}' class='tool div Designer Small' >Test Content </div>"));
        this.tools.push(new Control(true, "table", "Table", "tr td", "<table id='{0}' class='tool table'><tr><th>Column1</th><th>Column2</th></tr><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr>"));
        this.tools.push(new Control(true, "td", "Cell", "", "<td id='{0}' class='tool td'> Test Cell </td>"));
        this.tools.push(new Control(true, "ul", "List", "li", "<ul id='{0}' class='tool ul'><li>List Item 1</li><li>List Item 2</li>"));
        this.tools.push(new Control(true, "ol", "Numbered List", "li", "<ol id='{0}' class='tool ol'><li>List Item 1</li><li>List Item 2</ol>"));
        this.tools.push(new Control(false, "text", "Input Text", "", "<input id='{0}' class='tool text' type='text' value='text me!'/>"));
        this.tools.push(new Control(false, "submit", "Button", "", "<div id='{0}' class='tool submit'><input type='submit' value='Press Mee!'/></div>"));
        this.tools.push(new Control(false, "textarea", "Text Area", "", "<textarea  id='{0}' class='tool textarea' type='text' cols='20' rows='10' value='text me!'></textarea>"));
        this.tools.push(new Control(true, "li", "ListItem", "", "<li id='{0}' class='tool li'> List Item Again </li>"));
        this.tools.push(new Control(true, "a", "ALink", "", "<a id='{0}' class='tool a' href='javascript:void(0);'> A dummy link </a>"));
        this.tools.push(new Control(true, "span", "Span", "", "<span id='{0}' class='tool span'> A dummy span </span>"));
        this.tools.push(new Control(false, "hr", "Horizontal Rule", "", "<div id='{0}' class='tool hr'><hr /></div>"));
        this.tools.push(new Control(true, "h1", "H1", "", "<div id='{0}' class='tool h1'><h1>h1 <h1/></div>"));
        this.tools.push(new Control(true, "h2", "H2", "", "<div id='{0}' class='tool h2'><h2>h2 <h2/></div>"));
        this.tools.push(new Control(true, "h3", "H3", "", "<div id='{0}' class='tool h3'><h3>h3 <h3/></div>"));
        this.tools.push(new Control(true, "h4", "H4", "", "<div id='{0}' class='tool h4'><h4>h4 <h4/></div>"));

    },

    requestTools: function() {
        //enable links to other pages.
    },

    render: function() {
        var builderStr = '<div id="Tools"><ul>';
        for (var a in this.tools) {
            var toolboxItem = this.tools[a];
            builderStr += "<li> <div class='tool " + toolboxItem.key + "'>" + toolboxItem.name + "</div></li>";
        }
        builderStr += "</ul></div>";

        $(this.container).append(builderStr);

        var accessor = this.container + " ul li ";
        $(accessor).each(function(idx, item) {
            $(this).draggable({ helper: 'clone', cursor: 'crosshair', zIndex: 2700 });
        });
    },

    appendItem: function(item, controlToAdd) {
        var toolname = item.split(" ")[1];
        var foundItem = '';
        var templateDesigner = this;
        for (var a in this.tools) {
            component = this.tools[a];
            if (component.key == toolname) {
                var element = this.addElement(component, controlToAdd);
                //find the appropriate template
                var templateHtml = String.format(component.template, element.id);

                var template = $(templateHtml);
                // can contain elements ?
                if (component.zone === true) {
                    this.enableDropOn(template, false);
                    //element supports multiple draggable & droppable zones..
                    if (component.multipleDropZoneSelector != '') {
                        template.find(component.multipleDropZoneSelector).each(function(idx, item) {
                            var subElement = templateDesigner.addSubElement(this, element);
                            var subElementTemplate = $(this).attr('id', subElement.id);
                            templateDesigner.enableDropOn(subElementTemplate, false);
                            templateDesigner.enableDragOn(subElementTemplate);
                        });
                    }
                }
                this.enableDragOn(template);
                controlToAdd.append(template);
            }
        }
    },

    // if an element is not greedy which means event propogation blocked!
    enableDropOn: function(item, mainItem) {
        $(item).droppable({
            greedy: !mainItem,
            //accept: ".toolbox-item",
            activeClass: 'droppable-active',
            hoverClass: 'droppable-hover',
            tolerance: 'pointer',
            drop: function(ev, ui) {
                var item = ui.helper.find("div").attr('class');
                if (item == undefined) {
                    draggedItem = ui.helper;
                    $(draggedItem).css({ top: '0px', left: '0px' });
                    $(this).append(draggedItem);
                } else {
                    designer.appendItem(item, $(this));
                }
            }
        });
    },
    enableDragOn: function(item) {
        item.draggable({ cursor: 'crosshair', zIndex: 2700, start: function(event, ui) {
            item.css({ width: '100px', height: '100px' });
        }
        });
    },

    addTreeItem: function(item) {
        this.elementTree.Add(item);
        this.refreshTree();
    },

    refreshTree: function() {
        $(this.treeContainer).find("#ToolboxTree").remove();
        $(this.treeContainer).append("<ul id='ToolboxTree'></ul>");
        $("#ToolboxTree").treeview();

        var branches = $(this.renderTreePart(this.elementTree.items)).appendTo("#ToolboxTree");

        $("#ToolboxTree").treeview({
            add: branches
        });


    },
    renderTreePart: function(nodes) {
        var text = '';
        for (var idx in nodes) {
            var node = nodes[idx];
            text += '<li>';
            text += '<a href="javascript:void(0);" onclick="Highlight(\''+node.id+'\');">' + node.type.name + "</a>";
            if (node.childs.length > 0) {
                text += "<ul>";
                text += this.renderTreePart(node.childs);
                text += "</ul>";
            }
            text += "<li>"
        }
        return text;
    },


    initializeTree: function(item) {
        return;
        $(this.treeContainer).append("<ul id='ToolboxTree'><li> Main Holder <ul><li>Default Item</li></ul> </li></ul>");
        $("#ToolboxTree").treeview();
        var branches = $("<li><span class='folder'>New Sublist</span><ul>" +
				"<li><span class='file'>Item1</span></li>" +
				"<li><span class='file'>Item2</span></li></ul></li>").appendTo("#ToolboxTree");
        $("#ToolboxTree").treeview({
            add: branches
        });
    },
    addElement: function(component, controlToAdd) {
        /// <summary>adds the element to the control hierarchy</summary>
        /// <parameter name="component" type="Control"></parameter>
        /// <parameter name="controlToAdd" type="jQ()">
        /// a Reference to the droppable zone
        ///</parameter>
        var id = UID();
        var type = component;
        var settings = [];

        var newElement = new Element(id, type, settings, []);
        var lookingForElement = controlToAdd.attr("id");

        var parentElement = this.findControlInElementTree(lookingForElement, this.elementTree.items);

        if (parentElement != undefined) {
            parentElement.childs.push(newElement);
            this.refreshTree();
        }
        else {
            this.addTreeItem(newElement);
        }
        return newElement;
    },
    addSubElement: function(subelement, parentElement) {
        console.log(String.format("{0} for {1}={2}", subelement, parentElement.id, parentElement.type.key));

        var elementTags = parentElement.type.multipleDropZoneSelector.split(" ");
        var foundElementControl = this.findElementControl(elementTags[elementTags.length - 1]);
        var newSubElement = new Element(UID(), foundElementControl, [], []);
        parentElement.childs.push(newSubElement);
        return newSubElement;
    },
    findControlInElementTree: function(element, node) {
        for (var idx in node) {
            var item = node[idx];
            if (item.id == element) {
                return item;
            }
            else if (item.childs.length > 0) {
                return this.findControlInElementTree(element, item.childs);
            }
        }
    },
    findElementControl: function(lookFor) {
        for (el in this.tools) {
            if (this.tools[el].key == lookFor) {
                return this.tools[el];
            }
        }
    },

    findParent: function() {

    }


};

function UID(){
   return Math.random().toString().replace(".", "").replace(",", "");
}

function Highlight(id) {
    $("#"+ id).effect( 'highlight' , 3000 );
}
 